/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package eu.fastl.dragster.log.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Pattern;

import eu.fastl.dragster.log.service.LogParserResult;
import eu.fastl.dragster.log.service.LogParserService;
import eu.fastl.dragster.model.ExecutionRecord;
import eu.fastl.dragster.model.ExecutionRecordFactoryProvider;

/**
 * Simple implementation of {@LogParserService}
 * @author Robert Benak
 *
 */
public class LogParserServiceSimpleImpl implements LogParserService {

    private final Pattern PATTERN = Pattern.compile("\\|");
	private final Pattern PATTERN_BRACKET_OPEN = Pattern.compile("[",Pattern.LITERAL);
    private final Pattern PATTERN_BRACKET_CLOSE = Pattern.compile("]",Pattern.LITERAL);
    private final Pattern PATTERN_INFO_START = Pattern.compile("INFO - ",Pattern.LITERAL);


	public LogParserResult parseFile(File file) {
	    final List<ExecutionRecord> executionRecordList = new ArrayList<ExecutionRecord>();
	    final Map<String,List<ExecutionRecord>> executionRecordsByTypeMap = new HashMap<String,List<ExecutionRecord>>();
	    final Map<Object,List<ExecutionRecord>> executionRecordsByIdMap = new HashMap<Object,List<ExecutionRecord>>();
	    LogParserResult retval = new LogParserResult(executionRecordList, executionRecordsByTypeMap, executionRecordsByIdMap);
		try {
			FileInputStream fileInputStream = new FileInputStream(file);
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
			String line = "";
			ExecutionRecord executionRecord = null;
			int i=0;
			while((line = bufferedReader.readLine()) != null) {
				executionRecord = processLine(line);
				if (executionRecord != null) {
				    processExecutionRecord(executionRecord,executionRecordList,executionRecordsByTypeMap,executionRecordsByIdMap);
				}
				if (i%5000 == 0) System.out.println(i);
				i++;
                                line = "";
			}
			bufferedReader.close();
			return retval;
		} catch (Exception e) {
		    return new LogParserResult(new ArrayList<ExecutionRecord>(), new HashMap<String, List<ExecutionRecord>>(), new HashMap<Object, List<ExecutionRecord>>());
//			throw new IllegalStateException(e);
		}
	}

	protected ExecutionRecord processLine(String line) {
		if (!line.startsWith("INFO - [")) return null;
		line = this.PATTERN_INFO_START.matcher(line).replaceFirst("");
        line = this.PATTERN_BRACKET_OPEN.matcher(line).replaceAll("");
        line = this.PATTERN_BRACKET_CLOSE.matcher(line).replaceAll("|");
	    Scanner scanner = new Scanner(line);
		scanner.useDelimiter(this.PATTERN);
        String uniqueIdString = scanner.next();
		long uniqueId = Long.parseLong(uniqueIdString);
		String type = scanner.next();
		String detail = scanner.next();
		String timeString = scanner.next();
		timeString = timeString.replace("ms", "");
		long time = Long.parseLong(timeString);
		scanner.close();
        ExecutionRecord executionRecord = ExecutionRecordFactoryProvider.getExecutionRecordFactory().create(time, uniqueId, type, detail);
        return executionRecord;
	}

	protected void processExecutionRecord(ExecutionRecord executionRecord, List<ExecutionRecord> executionRecordList, Map<String, List<ExecutionRecord>> executionRecordsByTypeMap, Map<Object, List<ExecutionRecord>> executionRecordsByIdMap) {
		executionRecordList.add(executionRecord);

		if (executionRecordsByTypeMap.containsKey(executionRecord.getType())) {
			List<ExecutionRecord> executionRecordsListForMap = executionRecordsByTypeMap.get(executionRecord.getType());
			executionRecordsListForMap.add(executionRecord);
		}
		else {
			List<ExecutionRecord> executionRecordsListForMap = new ArrayList<ExecutionRecord>();
			executionRecordsListForMap.add(executionRecord);
			executionRecordsByTypeMap.put(executionRecord.getType(),executionRecordsListForMap);
		}

		if (executionRecordsByIdMap.containsKey(executionRecord.getUniqueId())) {
			List<ExecutionRecord> executionRecordsListForMap = executionRecordsByIdMap.get(executionRecord.getUniqueId());
			executionRecordsListForMap.add(executionRecord);
		}
		else {
			List<ExecutionRecord> executionRecordsListForMap = new ArrayList<ExecutionRecord>();
			executionRecordsListForMap.add(executionRecord);
			executionRecordsByIdMap.put(executionRecord.getUniqueId(),executionRecordsListForMap);
		}


	}

}
